package yicr.untils.gis.Polygon;





import yicr.untils.gis.NslUtilGis;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

public class NslUtilPolygon {

    static public NslPolygon createSector(double lng, double lat, double radius , double sAngle, double eAngle,String id){
        NslPolygon polygon=createSector(lng,lat,radius,sAngle,eAngle);
        polygon.setId(id);
        return polygon;
    }
    /**
     * 根据经纬度，半径、起始、最终角度绘制扇形，
     * 注意角度的定义，正西到正东，同平时的数学定义一致
     * @param lng 经度
     * @param lat 纬度
     * @param radius 半径 米
     * @param sAngle 起始角度
     * @param eAngle 结束角度
     * @return
     */
    static public NslPolygon createSector(double lng, double lat, double radius , double sAngle, double eAngle){
        if(sAngle>eAngle){
            throw  new RuntimeException(" 终止角度应大于起始角度");
        }
        int amount=1000;
        amount=300;
//        amount=2;
        double step=(eAngle-sAngle)/amount;

        List<Point2D.Double> pointList=new ArrayList<>();

        Point2D.Double originPoint=new Point2D.Double();
        originPoint.setLocation(lng,lat);

        pointList.add(originPoint);

        double currentAngle=sAngle;

        while(currentAngle<eAngle){
            Point2D.Double currentPoint=calPointOnSector(originPoint,radius,currentAngle);
            pointList.add(currentPoint);
            currentAngle+=step;
        }

        pointList.add(calPointOnSector(originPoint,radius,eAngle));

        NslPolygon nslPolygon =new NslPolygon(pointList);

        return nslPolygon;
    }

    /**
     * 根据 圆点坐标、半径，角度，计算在扇形点上的坐标
     * @param originPoint
     * @param radius
     * @param currentAngle
     * @return
     */
    private static Point2D.Double calPointOnSector(Point2D.Double originPoint, double radius, double currentAngle) {
        //单位1经度差值下，对应的距离
        double baseLng= NslUtilGis.getDistance(originPoint,new Point2D.Double(originPoint.getX()+0.1,originPoint.getY()))*10;
        double baseLat= NslUtilGis.getDistance(originPoint,new Point2D.Double(originPoint.getX(),originPoint.getY()+0.1))*10;

        double offsetLat=radius*Math.sin(currentAngle*Math.PI/180)/baseLat;
        double offsetLng=radius*Math.cos(currentAngle*Math.PI/180)/baseLng;
        Point2D.Double offsetPoint=new Point2D.Double(originPoint.getX()+offsetLng,originPoint.getY()+offsetLat);

        return offsetPoint;
    }


    static public double getArea(List<Point2D.Double> pointList){
        if(listSizeError(pointList)){
            return -1;
        }

        int i, j;
        double area = 0;
        for (i = 0; i < pointList.size(); i++)
        {
            j = (i + 1) % pointList.size();
            area += pointList.get(i).getX() * pointList.get(j).getY();
            area -= pointList.get(i).getY() * pointList.get(j).getX();
        }
        area /= 2;
        //System.out.println(Math.abs(area));
        return Math.abs(area);
    }


    /**
     * get gravity center of polygon.
     * @param pointList
     * @return
     */
    static  public Point2D.Double getGravityCenterOfPolygon(List<Point2D.Double> pointList){
        if(listSizeError(pointList)){
            return new Point2D.Double(-1,-1);
        }

        double gravityLat=0;
        double gravityLng=0;
        double area=getArea(pointList);
        int size=pointList.size();

        for (int i = 0; i < pointList.size(); i++) {
            double longitude=pointList.get(i).getX();
            double latitude=pointList.get(i).getY();
            double longitudeNext=pointList.get((i+1)%size).getX();
            double latitudeNext=pointList.get((i+1)%size).getY();

            double tempArea=(latitude*longitudeNext-longitude*latitudeNext)/2;

            gravityLat+=tempArea*(latitude+latitudeNext)/3;
            gravityLng+=tempArea*(longitude+longitudeNext)/3;
        }

        gravityLat=Math.abs(gravityLat/area);
        gravityLng=Math.abs(gravityLng/area);

        return new  Point2D.Double(gravityLng,gravityLat);
    }

    static public Point2D.Double getGravityCenterOfPolygon(NslPolygon nslPolygon) {
        if (listSizeError(nslPolygon.getPointList())) {
            return new Point2D.Double(-1, -1);
        }
        return getGravityCenterOfPolygon(nslPolygon.getPointList());
    }

    static boolean  listSizeError(List<Point2D.Double> pointList){
        if(pointList==null || pointList.size()<3){
            return true;
        }
        return false;
    }

}
